package com.engine4cloud.tdf.supervision.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.engine4cloud.tdf.admin.api.feign.RemoteDeptService;
import com.engine4cloud.tdf.common.core.constant.SecurityConstants;
import com.engine4cloud.tdf.common.core.exception.ValidateCodeException;
import com.engine4cloud.tdf.common.core.util.R;
import com.engine4cloud.tdf.common.core.util.RetOps;
import com.engine4cloud.tdf.common.core.util.lambda.Actions;
import com.engine4cloud.tdf.common.data.web.query.Pages;
import com.engine4cloud.tdf.common.data.web.query.Queries;
import com.engine4cloud.tdf.common.data.web.response.PageInfo;
import com.engine4cloud.tdf.common.data.web.response.Params;
import com.engine4cloud.tdf.supervision.convert.JzdxTerminalManageConvert;
import com.engine4cloud.tdf.supervision.dto.create.JzdxTerminalManageCreateDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxLocPhoneQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxTerminalManageQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxTerminalQueryDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxLocPhoneResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxTerminalManageResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxTerminalNeedLocResultDTO;
import com.engine4cloud.tdf.supervision.dto.update.JzdxTerminalManageUpdateDTO;
import com.engine4cloud.tdf.supervision.entity.JzdxTerminalManageEntity;
import com.engine4cloud.tdf.supervision.mapper.JzdxTerminalManageMapper;
import com.engine4cloud.tdf.supervision.service.JzdxService;
import com.engine4cloud.tdf.supervision.service.JzdxTerminalManageService;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 矫正对象-监管设备绑定
 *
 * @author wenjie
 * @date 2024-04-19 11:21:59
 */
@Service
public class JzdxTerminalManageServiceImpl extends ServiceImpl<JzdxTerminalManageMapper, JzdxTerminalManageEntity> implements JzdxTerminalManageService {
    @Resource
    private JzdxService jzdxService;

    @Resource
    private RemoteDeptService remoteDeptService;

    @Override
    public PageInfo<JzdxTerminalManageResultDTO> getTerminalManagePage(Params pageable, JzdxTerminalManageQueryDTO dto) {
        Page<JzdxTerminalManageEntity> page = page(Pages.page(pageable), wrapper(dto));
        return Pages.convert(page, JzdxTerminalManageConvert.INSTANCE::convert);
    }

    @Override
    public JzdxTerminalManageResultDTO getById(Long id) {
        return JzdxTerminalManageConvert.INSTANCE.convert(super.getById(id));
    }

    @Override
    public Boolean create(JzdxTerminalManageCreateDTO dto) {
        JzdxResultDTO dx = Optional.ofNullable(jzdxService.getByCode(dto.getRybh()))
                .orElseThrow(() -> new ValidateCodeException("矫正对象数据不存在"));

        this.checkParam(dto.getLocPhone(), dto.getPhoneIdentity(), dto.getWatchImei(), dto.getWatchType());
        this.checkUnique(null, dto.getLocPhone(), dto.getPhoneIdentity(), dto.getWatchImei());
        return super.save(JzdxTerminalManageConvert.INSTANCE.create(dto, dx.getTenantId()));
    }

    @Override
    public Boolean update(JzdxTerminalManageUpdateDTO dto) {
        JzdxTerminalManageEntity old = Optional.ofNullable(super.getById(dto.getId()))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        this.checkParam(dto.getLocPhone(), dto.getPhoneIdentity(), dto.getWatchImei(), dto.getWatchType());
        this.checkUnique(dto.getId(), dto.getLocPhone(), dto.getPhoneIdentity(), dto.getWatchImei());
        return super.updateById(JzdxTerminalManageConvert.INSTANCE.update(dto));
    }

    private void checkParam(String locPhone, String phoneIdentity, String imei, String type) {
        if (StringUtils.isEmpty(locPhone) && StringUtils.isEmpty(phoneIdentity) && StringUtils.isEmpty(imei)) {
            throw new ValidateCodeException("设备编号和手机号码不能全为空!");
        }

        if (StringUtils.isNotEmpty(imei) && Objects.isNull(type)) {
            throw new ValidateCodeException("腕表类型不能为空");
        }
    }

    @Override
    public Boolean checkUnique(Long id, String locPhone, String phoneIdentity, String imei) {
        Actions.apply(StringUtils.isNotEmpty(locPhone), () -> {
            JzdxTerminalManageQueryDTO query = new JzdxTerminalManageQueryDTO();
            query.setLocPhone(locPhone);
            Optional<JzdxTerminalManageEntity> optional = Optional.ofNullable(getOne(wrapper(query)));
            if (!optional.map(terminal -> Objects.equals(terminal.getId(), id)).orElse(true)) {
                throw new ValidateCodeException("基站定位手机号码已存在");
            }
        });

        Actions.apply(StringUtils.isNotEmpty(phoneIdentity), () -> {
            JzdxTerminalManageQueryDTO query = new JzdxTerminalManageQueryDTO();
            query.setPhoneIdentity(phoneIdentity);
            Optional<JzdxTerminalManageEntity> optional = Optional.ofNullable(getOne(wrapper(query)));
            if (!optional.map(terminal -> Objects.equals(terminal.getId(), id)).orElse(true)) {
                throw new ValidateCodeException("手机唯一编码标识重复");
            }
        });

        Actions.apply(StringUtils.isNotEmpty(imei), () -> {
            JzdxTerminalManageQueryDTO query = new JzdxTerminalManageQueryDTO();
            query.setWatchImei(imei);
            Optional<JzdxTerminalManageEntity> optional = Optional.ofNullable(getOne(wrapper(query)));
            if (!optional.map(terminal -> Objects.equals(terminal.getId(), id)).orElse(true)) {
                throw new ValidateCodeException("腕表imei已存在");
            }
        });

        return true;
    }

    @Override
    public PageInfo<JzdxLocPhoneResultDTO> locPhoneList(JzdxLocPhoneQueryDTO dto) {
        List<Long> deptIdList = Collections.emptyList();

        if (Objects.nonNull(dto.getDeptId())) {
            R<List<Long>> deptIdRemoteList = remoteDeptService.getDescendantIdList(dto.getDeptId(), SecurityConstants.FROM_IN);

            deptIdList = RetOps.of(deptIdRemoteList).getData().filter(CollectionUtils::isNotEmpty)
                    .orElseThrow(() -> new ValidateCodeException("没有数据权限!"));
        }

        return Pages.convert(this.baseMapper.locPhoneList(Pages.page(dto), dto, deptIdList));
    }

    @Override
    public void removeByCode(String code) {
        LambdaQueryWrapper<JzdxTerminalManageEntity> wrapper = Queries.lambda();
        Queries.accept(code, v -> wrapper.eq(JzdxTerminalManageEntity::getRybh, v));
        this.remove(wrapper);
    }

    @Override
    public JzdxTerminalManageResultDTO findOne(JzdxTerminalManageQueryDTO dto) {
        return JzdxTerminalManageConvert.INSTANCE.convert(getOne(wrapper(dto)));
    }

    @Override
    public JzdxTerminalManageResultDTO findByTerminal(JzdxTerminalQueryDTO dto) {
        if (StringUtils.isEmpty(dto.getWatchImei()) && StringUtils.isEmpty(dto.getPhoneIdentity()) && StringUtils.isEmpty(dto.getLocPhone())) {
            throw new ValidateCodeException("设备编号和手机号码不能全为空!");
        }

        return this.baseMapper.findByTerminal(dto);
    }

    @Override
    public List<JzdxTerminalNeedLocResultDTO> findNeedLoc(Long deptId) {
        R<List<Long>> deptIdRemoteList = remoteDeptService.getDescendantIdList(deptId, SecurityConstants.FROM_IN);

        List<Long> deptIdList = RetOps.of(deptIdRemoteList).getData().filter(CollectionUtils::isNotEmpty).orElse(null);
        if (CollectionUtils.isEmpty(deptIdList)) {
            return Collections.emptyList();
        }

        return this.baseMapper.findNeedLoc(deptIdList);
    }

    private LambdaQueryWrapper<JzdxTerminalManageEntity> wrapper(JzdxTerminalManageQueryDTO query) {
        LambdaQueryWrapper<JzdxTerminalManageEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(JzdxTerminalManageEntity::getId, v));
        Queries.accept(query.getRybh(), v -> wrapper.eq(JzdxTerminalManageEntity::getRybh, v));
        Queries.accept(query.getLocPhone(), v -> wrapper.eq(JzdxTerminalManageEntity::getLocPhone, v));
        Queries.accept(query.getPhoneIdentity(), v -> wrapper.eq(JzdxTerminalManageEntity::getPhoneIdentity, v));
        Queries.accept(query.getWatchImei(), v -> wrapper.eq(JzdxTerminalManageEntity::getWatchImei, v));
        Queries.accept(query.getWatchType(), v -> wrapper.eq(JzdxTerminalManageEntity::getWatchType, v));
        return wrapper;
    }
}